#
# This file is a part of the open-eBackup project.
# This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
# If a copy of the MPL was not distributed with this file, You can obtain one at
# http://mozilla.org/MPL/2.0/.
#
# Copyright (c) [2024] Huawei Technologies Co.,Ltd.
#
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
#

import json
import os
import sys

from common.common import execute_cmd
from common.common_models import SubJobDetails
from common.const import SubJobStatusEnum, RepositoryDataTypeEnum
from sqlserver import log
from sqlserver.commons.common import check_del_dir_or_file
from sqlserver.commons.const import SQLServerJsonConstant, ParamConstant, SQLServerProgressFileType, ExecCmdResult
from sqlserver.sqlserver_base import SQLServerBase


class DeleteCopies:
    def __init__(self, pid, job_id, sub_job_id=None):
        self.pid = pid
        self.job_id = job_id
        self.sub_job_id = sub_job_id

    def get_copies_data_path(self):
        """
        解析参数文件，获取当前任务的副本路径
        :return: 副本路径列表
        """
        copies_path = []
        parm_path = os.path.join(ParamConstant.PARAM_FILE_PATH, f"param{self.pid}")
        try:
            param_dict = SQLServerBase.read_temp_file(parm_path)
        except Exception as ex:
            log.exception(f"Job id: {self.job_id} failed to parse param file. err msg: {ex}.")
            return copies_path
        finally:
            check_del_dir_or_file(parm_path)

        copy_info = param_dict.get("job", {}).get("copies", [{}])
        for copy_item in copy_info:
            copy_type = copy_item.get(SQLServerJsonConstant.TYPE, "")
            copy_id = copy_item.get(SQLServerJsonConstant.ID, "")
            repositories_info = copy_item.get(SQLServerJsonConstant.REPOSITORIES, {})
            data_pathes = self.parse_repositories_info(repositories_info)
            copies_path.extend(data_pathes)

        return copies_path

    def delete_copies_info(self):
        """
        删除副本信息
        :return: 删除结果, 接口返回格式结果
        """
        log.info(f'Delete copies info start, Job id: {self.job_id}.')
        action_result = SubJobDetails(taskId=self.job_id, subTaskId=self.sub_job_id,
                                      taskStatus=SubJobStatusEnum.FAILED.value, progress=int(30))
        copies_path = self.get_copies_data_path()
        if not copies_path:
            log.error(f'Delete copies info, Job id: {self.job_id} can not get copy path.')
            self.report_delete_job_details(action_result)
            return action_result

        for data_path in copies_path:
            try:
                check_del_dir_or_file(data_path)
            except Exception as exception:
                log.exception(
                    f"Job id: {self.job_id} exec delete copy dir: {data_path} failed. err msg: {exception}.")
                self.report_delete_job_details(action_result)
                return action_result

            log.info(f"Job id: {self.job_id} exec delete copy dir: {data_path} success.")

        log.info(f'Delete copies info success end, job id: {self.job_id}.')
        action_result.task_status = SubJobStatusEnum.COMPLETED.value
        action_result.progress = int(100)
        self.report_delete_job_details(action_result)
        return action_result

    def delete_copies_progress(self):
        """
        删除副本进度查询
        :return: 查询结果, 接口返回格式结果
        """
        log.info(f'Delete copies progress start, Job id: {self.job_id}.')
        action_result = SubJobDetails(taskId=self.job_id, subTaskId=self.sub_job_id,
                                      taskStatus=SubJobStatusEnum.FAILED.value, progress=int(100))

        copy_exist = False
        copies_path = self.get_copies_data_path()
        if not copies_path:
            log.error(f'Delete copies progress, Job id: {self.job_id} can not get copy path.')
            return action_result

        for data_path in copies_path:
            if os.path.exists(data_path):
                log.error(f"Delete copies progress dir: {data_path} exist, Job id: {self.job_id}.")
                copy_exist = True
                break

        if not copy_exist:
            action_result.task_status = SubJobStatusEnum.COMPLETED.value
            log.info(f'Delete copies progress success end, Job id: {self.job_id}.')

        return action_result

    def report_delete_job_details(self, action_result):
        log.info("Start to report delete job details, job id: %s, pid: %s.", self.job_id, self.pid)
        report_job_param_file = os.path.join(ParamConstant.PARAM_FILE_PATH,
                                             SQLServerProgressFileType.REPORT_PROGRESS_PARAM + self.pid)
        SQLServerBase.write_context_to_tmp_file(json.dumps(action_result.dict(by_alias=True)), report_job_param_file)
        report_job_out_file = os.path.join(ParamConstant.PARAM_FILE_PATH,
                                           SQLServerProgressFileType.REPORT_JOB_PROGRESS + self.pid)
        cmd = f"\"{ParamConstant.RPC_TOOL}\" ReportJobDetails \"{report_job_param_file}\" \"{report_job_out_file}\""
        code, out, err = execute_cmd(cmd)
        # 清理临时文件：
        check_del_dir_or_file(report_job_param_file)
        check_del_dir_or_file(report_job_out_file)
        if code != ExecCmdResult.SUCCESS:
            log.error(f"Failed to report delete job details, as code: %s, out: %s, err: %s, job id: %s, pid: %s.", code,
                      out, err, self.job_id, self.pid)
            raise Exception("Failed to report delete job details.")
        log.info("Succeed to report delete job details, job id: %s, pid: %s.", self.job_id, self.pid)

    def parse_repositories_info(self, repositories_info):
        path_map = []
        for repository in repositories_info:
            rep_type = repository.get(SQLServerJsonConstant.REPOSITORY_TYPE)
            if rep_type in (RepositoryDataTypeEnum.DATA_REPOSITORY, RepositoryDataTypeEnum.META_REPOSITORY,
                            RepositoryDataTypeEnum.LOG_REPOSITORY):
                rep_path = repository.get("path", [])
                if not rep_path:
                    log.error(f'Job id: {self.job_id} get path failed.')
                    return path_map
                rep_path = rep_path[0]
                path_map.append(rep_path)
        return path_map


if __name__ == "__main__":
    log.info("sys argv: %s", sys.argv)
    job_type = sys.argv[1]
    delete_copies_obj = DeleteCopies(*sys.argv[2:])
    job_func_dict = {
        "delete": delete_copies_obj.delete_copies_info,
    }
    job_func = job_func_dict.get(job_type)
    try:
        result = job_func()
    except Exception as e:
        log.exception(e)
        sys.exit(1)
    sys.exit(0)
